This example demonstrates how to map dwelling units by primary rensidence status and structural type for primary residences. ## Data First we grab the building data via cancensus, making use of the CensusMapper API tool to select the regions and variables we need.
#devtools::install_github("mountainmath/cancensus")
library(cancensus)
library(dotdensity)
library(cancensusHelpers)
# options(cancensus.api_key='your_api_key')
dataset='CA16'
regions=list(CSD="3520005")
vectors <- search_census_vectors("structural type of dwelling",dataset) %>%
child_census_vectors(TRUE) %>%
pull(vector)
We choose the categories and colours we want to map and define a convenience function to rename the variables and compute the qantities for the other asian countries that we don’t break out.
labels=list(v_CA16_417="Movable Dwelling",
v_CA16_409="Single Detached",
v_CA16_416="Other Single Attached",
v_CA16_414="Duplex",
v_CA16_412="Semi Detached",
v_CA16_413="Row House",
v_CA16_415="Apartment, < 5 storeys",
v_CA16_410="Apartment, >= 5 storeys")
categories=c("Non-primary Residence",as.character(labels))
colors=setNames(
c("#cccccc","#7a0177", "#ffff00", "#ffcc00", "#ff6600", "#ff0066", "#ff00ff", "#4dff4a", "#00ffff"),
categories)
prep_data <- function(geo){
data <- geo %>% replace(is.na(.), 0)
names(data)[names(data) %in% names(labels)] <- as.character(labels[names(data)[names(data) %in% names(labels)]])
data %>% mutate(`Non-primary Residence`=Dwellings - Households)
}
Next we grab the data via cancensus,
data_csd=get_census(dataset = dataset, regions=regions,vectors=vectors,geo_format='sf',labels='short',level='CSD') %>% prep_data
data_ct=get_census(dataset = dataset, regions=regions,vectors=vectors,geo_format='sf',labels='short',level='CT') %>% prep_data
data_da=get_census(dataset = dataset, regions=regions,vectors=vectors,geo_format='sf',labels='short',level='DA') %>% prep_data
data_db=get_census(dataset = dataset, regions=regions,geo_format='sf',labels='short',level='DB')
which we then re-aggregate to make sure we don’t miss overall counts due to privacy cutoffs distribute them proportionally among the population.
data_ct <- dot_density.proportional_re_aggregate(data=data_ct,
parent_data=data_csd,
geo_match=setNames("GeoUID","CSD_UID"),
categories=categories,base="Dwellings")
data_da <- dot_density.proportional_re_aggregate(data=data_da,
parent_data=data_ct,
geo_match=setNames("GeoUID","CT_UID"),
categories=categories,base="Dwellings")
data_db <- dot_density.proportional_re_aggregate(data=data_db,
parent_data=data_da,
geo_match=setNames("GeoUID","DA_UID"),
categories=categories,base="Dwellings")
Map
All that’s left to do is to covert our re-aggregated block-level data to dots, using the dot_density.compute_dots function from the dotdensity package and feed it into the dot_density.dots_map function to add them to our basemap.

LS0tCnRpdGxlOiAiQnVpbGRpbmcgVHlwZXMiCmF1dGhvcjogIkplbnMgdm9uIEJlcmdtYW5uIgpkYXRlOiAiMjAxNy0wOC0zMCIKb3V0cHV0OiBodG1sX25vdGVib29rCnZpZ25ldHRlOiA+CiAgJVxWaWduZXR0ZUluZGV4RW50cnl7QnVpbGRpbmcgVHlwZXN9CiAgJVxWaWduZXR0ZUVuZ2luZXtrbml0cjo6cm1hcmtkb3dufQogICVcVmlnbmV0dGVFbmNvZGluZ3tVVEYtOH0KLS0tCgpUaGlzIGV4YW1wbGUgZGVtb25zdHJhdGVzIGhvdyB0byBtYXAgZHdlbGxpbmcgdW5pdHMgYnkgcHJpbWFyeSByZW5zaWRlbmNlIHN0YXR1cyBhbmQgc3RydWN0dXJhbCB0eXBlIGZvciBwcmltYXJ5IHJlc2lkZW5jZXMuCiMjIERhdGEKRmlyc3Qgd2UgZ3JhYiB0aGUgYnVpbGRpbmcgZGF0YSB2aWEgW2NhbmNlbnN1c10oaHR0cHM6Ly9naXRodWIuY29tL21vdW50YWluTWF0aC9jYW5jZW5zdXMpLCBtYWtpbmcgdXNlIG9mIHRoZSBbQ2Vuc3VzTWFwcGVyIEFQSSB0b29sXShodHRwczovL2NlbnN1c21hcHBlci5jYS9hcGkvQ0ExMSkgdG8gc2VsZWN0IHRoZSByZWdpb25zIGFuZCB2YXJpYWJsZXMgd2UgbmVlZC4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNkZXZ0b29sczo6aW5zdGFsbF9naXRodWIoIm1vdW50YWlubWF0aC9jYW5jZW5zdXMiKQpsaWJyYXJ5KGNhbmNlbnN1cykKbGlicmFyeShkb3RkZW5zaXR5KQpsaWJyYXJ5KGNhbmNlbnN1c0hlbHBlcnMpCiMgb3B0aW9ucyhjYW5jZW5zdXMuYXBpX2tleT0neW91cl9hcGlfa2V5JykKZGF0YXNldD0nQ0ExNicKcmVnaW9ucz1saXN0KENTRD0iMzUyMDAwNSIpCnZlY3RvcnMgPC0gc2VhcmNoX2NlbnN1c192ZWN0b3JzKCJzdHJ1Y3R1cmFsIHR5cGUgb2YgZHdlbGxpbmciLGRhdGFzZXQpICU+JQogIGNoaWxkX2NlbnN1c192ZWN0b3JzKFRSVUUpICU+JSAgCiAgcHVsbCh2ZWN0b3IpCmBgYAoKV2UgY2hvb3NlIHRoZSBjYXRlZ29yaWVzIGFuZCBjb2xvdXJzIHdlIHdhbnQgdG8gbWFwIGFuZCBkZWZpbmUgYSBjb252ZW5pZW5jZSBmdW5jdGlvbiB0byByZW5hbWUgdGhlIHZhcmlhYmxlcyBhbmQgY29tcHV0ZSB0aGUgcWFudGl0aWVzIGZvciB0aGUgb3RoZXIgYXNpYW4gY291bnRyaWVzIHRoYXQgd2UgZG9uJ3QgYnJlYWsgb3V0LgpgYGB7cn0KCmxhYmVscz1saXN0KHZfQ0ExNl80MTc9Ik1vdmFibGUgRHdlbGxpbmciLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgdl9DQTE2XzQwOT0iU2luZ2xlIERldGFjaGVkIiwKICAgICAgICAgICAgdl9DQTE2XzQxNj0iT3RoZXIgU2luZ2xlIEF0dGFjaGVkIiwKICAgICAgICAgICAgdl9DQTE2XzQxND0iRHVwbGV4IiwKICAgICAgICAgICAgdl9DQTE2XzQxMj0iU2VtaSBEZXRhY2hlZCIsCiAgICAgICAgICAgIHZfQ0ExNl80MTM9IlJvdyBIb3VzZSIsCiAgICAgICAgICAgIHZfQ0ExNl80MTU9IkFwYXJ0bWVudCwgPCA1IHN0b3JleXMiLAogICAgICAgICAgICB2X0NBMTZfNDEwPSJBcGFydG1lbnQsID49IDUgc3RvcmV5cyIpCgpjYXRlZ29yaWVzPWMoIk5vbi1wcmltYXJ5IFJlc2lkZW5jZSIsYXMuY2hhcmFjdGVyKGxhYmVscykpCmNvbG9ycz1zZXROYW1lcygKICBjKCIjY2NjY2NjIiwiIzdhMDE3NyIsICIjZmZmZjAwIiwgIiNmZmNjMDAiLCAiI2ZmNjYwMCIsICIjZmYwMDY2IiwgIiNmZjAwZmYiLCAiIzRkZmY0YSIsICIjMDBmZmZmIiksCiAgY2F0ZWdvcmllcykKCgpwcmVwX2RhdGEgPC0gZnVuY3Rpb24oZ2VvKXsKICBkYXRhIDwtIGdlbyAlPiUgcmVwbGFjZShpcy5uYSguKSwgMCkKICBuYW1lcyhkYXRhKVtuYW1lcyhkYXRhKSAlaW4lIG5hbWVzKGxhYmVscyldIDwtIGFzLmNoYXJhY3RlcihsYWJlbHNbbmFtZXMoZGF0YSlbbmFtZXMoZGF0YSkgJWluJSBuYW1lcyhsYWJlbHMpXV0pCiAgZGF0YSAlPiUgbXV0YXRlKGBOb24tcHJpbWFyeSBSZXNpZGVuY2VgPUR3ZWxsaW5ncyAtIEhvdXNlaG9sZHMpCn0KYGBgCgoKTmV4dCB3ZSBncmFiIHRoZSBkYXRhIHZpYSBgY2FuY2Vuc3VzYCwKYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGF0YV9jc2Q9Z2V0X2NlbnN1cyhkYXRhc2V0ID0gZGF0YXNldCwgcmVnaW9ucz1yZWdpb25zLHZlY3RvcnM9dmVjdG9ycyxnZW9fZm9ybWF0PSdzZicsbGFiZWxzPSdzaG9ydCcsbGV2ZWw9J0NTRCcpICU+JSBwcmVwX2RhdGEKZGF0YV9jdD1nZXRfY2Vuc3VzKGRhdGFzZXQgPSBkYXRhc2V0LCByZWdpb25zPXJlZ2lvbnMsdmVjdG9ycz12ZWN0b3JzLGdlb19mb3JtYXQ9J3NmJyxsYWJlbHM9J3Nob3J0JyxsZXZlbD0nQ1QnKSAlPiUgcHJlcF9kYXRhCmRhdGFfZGE9Z2V0X2NlbnN1cyhkYXRhc2V0ID0gZGF0YXNldCwgcmVnaW9ucz1yZWdpb25zLHZlY3RvcnM9dmVjdG9ycyxnZW9fZm9ybWF0PSdzZicsbGFiZWxzPSdzaG9ydCcsbGV2ZWw9J0RBJykgJT4lIHByZXBfZGF0YQpkYXRhX2RiPWdldF9jZW5zdXMoZGF0YXNldCA9IGRhdGFzZXQsIHJlZ2lvbnM9cmVnaW9ucyxnZW9fZm9ybWF0PSdzZicsbGFiZWxzPSdzaG9ydCcsbGV2ZWw9J0RCJykKYGBgCgp3aGljaCB3ZSB0aGVuIHJlLWFnZ3JlZ2F0ZSB0byBtYWtlIHN1cmUgd2UgZG9uJ3QgbWlzcyBvdmVyYWxsIGNvdW50cyBkdWUgdG8gcHJpdmFjeSBjdXRvZmZzIGRpc3RyaWJ1dGUgdGhlbQpwcm9wb3J0aW9uYWxseSBhbW9uZyB0aGUgcG9wdWxhdGlvbi4KYGBge3J9CmRhdGFfY3QgPC0gZG90X2RlbnNpdHkucHJvcG9ydGlvbmFsX3JlX2FnZ3JlZ2F0ZShkYXRhPWRhdGFfY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudF9kYXRhPWRhdGFfY3NkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9fbWF0Y2g9c2V0TmFtZXMoIkdlb1VJRCIsIkNTRF9VSUQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcmllcz1jYXRlZ29yaWVzLGJhc2U9IkR3ZWxsaW5ncyIpCmRhdGFfZGEgPC0gZG90X2RlbnNpdHkucHJvcG9ydGlvbmFsX3JlX2FnZ3JlZ2F0ZShkYXRhPWRhdGFfZGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudF9kYXRhPWRhdGFfY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb19tYXRjaD1zZXROYW1lcygiR2VvVUlEIiwiQ1RfVUlEIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3JpZXM9Y2F0ZWdvcmllcyxiYXNlPSJEd2VsbGluZ3MiKQpkYXRhX2RiIDwtIGRvdF9kZW5zaXR5LnByb3BvcnRpb25hbF9yZV9hZ2dyZWdhdGUoZGF0YT1kYXRhX2RiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRfZGF0YT1kYXRhX2RhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9fbWF0Y2g9c2V0TmFtZXMoIkdlb1VJRCIsIkRBX1VJRCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yaWVzPWNhdGVnb3JpZXMsYmFzZT0iRHdlbGxpbmdzIikKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKYmdfY29sb3I9IiM0NDQ0NDQiCmJhc2VfY29sb3I9IiMxMTExMTEiCnRleHRfY29sb3I9IiNlZWVlZWUiCnRoZW1lX29wdHM8LWxpc3QobWFwX3RoZW1lLAogICAgICAgICAgICAgICAgIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IGJnX2NvbG9yLCBjb2xvdXIgPSBOQSksCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9YmdfY29sb3IsIHNpemU9MSxsaW5ldHlwZT0ic29saWQiLGNvbG9yPXRleHRfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT04MCxoanVzdCA9IDAuNSwgY29sb3I9dGV4dF9jb2xvciksCiAgICAgICAgICAgICAgICAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTYwLGhqdXN0ID0gMC41LCBjb2xvcj10ZXh0X2NvbG9yKSwKICAgICAgICAgICAgICAgICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT0yNSwgY29sb3I9dGV4dF9jb2xvciksCiAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9NDAsIGNvbG9yPXRleHRfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MzAsIGNvbG9yPXRleHRfY29sb3IpLAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9YmdfY29sb3IsIHNpemU9MSxsaW5ldHlwZT0ic29saWQiLGNvbG9yPWJnX2NvbG9yKSwKICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGwgPSBiZ19jb2xvcixjb2xvciA9IGJnX2NvbG9yKSwKICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQua2V5LndpZHRoID0gdW5pdCgzLCAnbGluZXMnKSwKICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikpCgpiYXNlbWFwIDwtICAgZ2dwbG90KGRhdGFfY3NkKSArCiAgICBnZW9tX3NmKGZpbGwgPSBiYXNlX2NvbG9yLCBzaXplPTAuMSwgY29sb3IgPSAnZ3JleScpICsKICAgIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQobnJvdz0yLG92ZXJyaWRlLmFlcyA9IGxpc3Qoc2l6ZT0xNSkpKSArCiAgICAjY29vcmRfbWFwKHByb2plY3Rpb249ImxhbWJlcnQiLCBsYXQwPTQ5LCBsYXQ9NDkuNCkgKwogICAgdGhlbWVfb3B0cwoKYGBgCgoKIyNNYXAKQWxsIHRoYXQncyBsZWZ0IHRvIGRvIGlzIHRvIGNvdmVydCBvdXIgcmUtYWdncmVnYXRlZCBibG9jay1sZXZlbCBkYXRhIHRvIGRvdHMsIHVzaW5nIHRoZSBgZG90X2RlbnNpdHkuY29tcHV0ZV9kb3RzYApmdW5jdGlvbiBmcm9tIHRoZSBbYGRvdGRlbnNpdHlgIHBhY2thZ2VdKCkgYW5kIGZlZWQgaXQgaW50byB0aGUgYGRvdF9kZW5zaXR5LmRvdHNfbWFwYCBmdW5jdGlvbiB0byBhZGQgdGhlbSB0bwpvdXIgYmFzZW1hcC4KYGBge3IsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMywgbWVzc2FnZT1UUlVFLCB3YXJuaW5nPVRSVUV9CiMgMSBkb3QgPSB4IGR3ZWxsaW5nIHVuaXRzCnNjYWxlPTEwCgoKZG90cyA8LSBkb3RfZGVuc2l0eS5jb21wdXRlX2RvdHMoZ2VvX2RhdGEgPSBkYXRhX2RiLCBjYXRlZ29yaWVzID0gY2F0ZWdvcmllcywgc2NhbGU9c2NhbGUpCmJhc2VtYXAgKwogICMgem9vbSBpbiBhIGJpdAogICNjb29yZF9maXhlZCh4bGltPWMoLTEyMy4yOSwtMTIyLjYpLCB5bGltPWMoNDkuMDIsNDkuMzUpLCByYXRpbyA9IDEvY29zKDQ5LjIvMTgwKnBpKSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29sb3JzKSArCiAgbGFicyhjb2xvciA9ICIiLAogICAgICAgICAgICAgICAgdGl0bGU9IkR3ZWxsaW5nIFVuaXRzIDIwMTYiLAogICAgICAgICAgICAgICAgY2FwdGlvbj0iU291cmNlOiBTdGF0Q2FuIENlbnN1cyAyMDE2IHZpYSBjYW5jZW5zdXMgJiBDZW5zdXNNYXBwZXIuY2EiLAogICAgICAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIjEgZG90ID0gIixzY2FsZSwiIGR3ZWxsaW5nIHVuaXRzIikpICsgCiAgZG90X2RlbnNpdHkuZG90c19tYXAoZG90cz1kb3RzLGFscGhhPTAuOSxzaXplPTAuMjUpCgojIHNhdmUgaW1hZ2UgZm9yIGxhdGVyCmdnc2F2ZSgnLi4vaW1hZ2VzL2R3ZWxsaW5ncy5wbmcnLHdpZHRoPTI2LGhlaWdodD0yNikKYGBgCgo=